package com.eclink.asset.workflow.service;

import cn.hutool.core.lang.generator.SnowflakeGenerator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.eclink.asset.asset.convert.FlowApplyConvert;

import com.eclink.asset.asset.domain.dao.FlowApply;
import com.eclink.asset.asset.domain.form.ApplyFormDataZCDB;
import com.eclink.asset.asset.domain.query.AssetApplySaveQuery;
import com.eclink.asset.asset.service.AssetItemService;
import com.eclink.asset.common.domain.dto.CommonUserDTO;
import com.eclink.asset.convert.AssetItemConvert;
import com.eclink.asset.domain.dto.FlowApplyDetailDTO;
import com.eclink.asset.enums.ApplyStateEnum;
import com.eclink.asset.setup.service.CompanyService;
import com.eclink.asset.workflow.domain.dao.FlowTask;
import com.eclink.asset.workflow.mapper.FlowApplyMapper;
import com.eclink.asset.pojo.query.ApplyQuery;
import com.eclink.asset.service.AssetCategoryService;
import com.eclink.asset.service.CommonUserService;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

@Service
public class ApplyService {

    @Resource
    private FlowApplyMapper flowApplyMapper;

    @Autowired
    private SnowflakeGenerator idGenerator;

    @Autowired
    private CommonUserService commonUserService;

    @Resource
    private FlowService flowService;

    @Resource
    private FlowApplyConvert flowApplyConvert;

    @Autowired
    private AssetItemService assetItemService;

    @Autowired
    private AssetCategoryService assetCategoryService;

    @Autowired
    private AssetItemConvert assetItemConvert;

    @Resource
    private CompanyService companyService;

    /**
     * 编号后缀的长度 如：000001, 000002.....999999，则长度为6
     */
    private static final int NUMBER_APPEND_LENGTH = 6;

    private String getInApplyNumber(String applyType) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String numberPrefix = applyType + sdf.format(new Date(System.currentTimeMillis()));

        QueryWrapper<FlowApply> qw = new QueryWrapper<>();
        qw.likeRight("number", numberPrefix);
        qw.last("limit 1");
        qw.orderByDesc("number");
        FlowApply flowApply = flowApplyMapper.selectOne(qw);
        int orderNo = 1;

        if (flowApply != null) {
            String lastNumber = flowApply.getNumber();
            int numberLength = lastNumber.length();
            orderNo = Integer.parseInt(lastNumber.substring(numberLength - NUMBER_APPEND_LENGTH, numberLength)) + 1;
        }
        String numberAppend = "000000" + orderNo;
        numberAppend = numberAppend.substring(numberAppend.length() - NUMBER_APPEND_LENGTH);

        return numberPrefix + numberAppend;
    }

    /**
     * 查询入库申请列表
     *
     * @param query 查询条件
     * @param page 分页条件
     * @return 入库申请列表
     */
    public List<FlowApply> selectList(ApplyQuery query, Pageable page) {
        if (page != null) {
            PageHelper.startPage(page.getPageNumber() + 1, page.getPageSize());
        }
        LambdaQueryWrapper<FlowApply> qw = new LambdaQueryWrapper<>();
        qw.eq(FlowApply::getApplyType, query.getApplyType());
        qw.eq(FlowApply::getDelFlag,0);
        if (query.getUserId() != null && query.getUserId() > 0) {
            qw.eq(FlowApply::getCreateUserId, query.getUserId());
        }
        qw.orderByDesc(FlowApply::getId);
        List<FlowApply> list = flowApplyMapper.selectList(qw);
        for(FlowApply flowApply : list) {
            String nickName = commonUserService.getNickNameById(flowApply.getCreateUserId());
            flowApply.setCreateUserName(nickName);
        }
        return list;
    }

    public FlowApply addApply(FlowApply flowApply) {

        String id = String.valueOf(idGenerator.next());
        flowApply.setId(id);
        // 获取入库流程的配置
        flowApply.setNumber(this.getInApplyNumber(flowApply.getApplyType()));
        flowApply.setCreateTime(LocalDateTime.now());
        flowApply.setCreateUserId(SecurityUtils.getUserId());
        flowApply.setUpdateTime(LocalDateTime.now());
        flowApply.setUpdateUserId(SecurityUtils.getUserId());

        // 插入inApply表
        flowApplyMapper.insert(flowApply);
        return flowApply;

    }

    private void updateApply(FlowApply flowApply) {

        UpdateWrapper<FlowApply> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", flowApply.getId());
        updateWrapper.set("update_time", LocalDateTime.now());
        updateWrapper.set("update_user_id", SecurityUtils.getUserId());
        updateWrapper.set("form_data", flowApply.getFormData());
        updateWrapper.set("remark", flowApply.getRemark());
        // 插入inApply表
        flowApplyMapper.update(null, updateWrapper);

    }

    /**
     * 填充申请信息中的表单内容
     * @param formData
     * @return 填充后的表单内容
     */
    private String fillFormData(String formData) {

        JSONObject obj = JSON.parseObject(formData);

        // 如果有目标用户ID，填充目标用户姓名
        if (obj.get("targetUserId")!=null) {
            Long targetUserId = Long.valueOf(obj.get("targetUserId").toString());
            CommonUserDTO user = commonUserService.getUserById(targetUserId);
            obj.put("targetUserName", user.getNickName());
            obj.put("targetUserDeptName", user.getDeptName());
            obj.put("targetUserCompanyName", user.getCompanyName());
        }

        // 如果有管理员ID，填充管理员姓名
        if (obj.get("adminId")!=null) {
            Long adminId = Long.valueOf(obj.get("adminId").toString());
            String adminName = commonUserService.getNickNameById(adminId);
            obj.put("adminName", adminName);
        }
        // 如果有公司ID，填充公司名称
        if (obj.get("companyId") != null) {
            Long companyId = Long.valueOf(obj.get("companyId").toString());
            String companyName = companyService.getNameById(companyId);
            obj.put("companyName", companyName);
        }

        return obj.toJSONString();
    }

    /**
     * 保存入库申请
     * @param saveDTO dto
     */
    public void save(AssetApplySaveQuery saveDTO) {
        FlowApply flowApply = saveDTO.getApply();
        String formData = flowApply.getFormData();
        formData = fillFormData(formData);
        flowApply.setFormData(formData);
        if (saveDTO.isEdit()) {
            updateApply(flowApply);
        } else {
            addApply(flowApply);
        }
    }

    public void updateFlowId(String id, String flowId) {
        LambdaUpdateWrapper<FlowApply> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(FlowApply::getFlowId, flowId);
        updateWrapper.eq(FlowApply::getId, id);
        flowApplyMapper.update(null, updateWrapper);
    }

    /**
     * 提交入库申请
     * @param id id
     */
    @Transactional
    public void sub(String id) {
        FlowApply flowApply = flowApplyMapper.selectById(id);
        // 把申请的状态改成申请中
        flowApply.setState(ApplyStateEnum.APPROVING.getValue());
        flowApplyMapper.updateById(flowApply);

        // 创建工作流，并返回任务数，如果任务数为0，则工作流完成，开始执行任务
        String flowId = flowService.startFlow(flowApply);
        updateFlowId(id, flowId);

    }

    /**
     * 保存入库申请
     * @param saveDTO dto
     */
    public void saveAndSub(AssetApplySaveQuery saveDTO) {
        save(saveDTO);
        sub(saveDTO.getApply().getId());
    }

    /**
     * 删除入库申请
     * @param id id
     */
    public void delete(String id) {
        flowApplyMapper.deleteById(id);
    }

    public FlowApply getById(String id) {
        FlowApply flowApply = flowApplyMapper.selectById(id);
        if (flowApply!=null) {
            String nickName = commonUserService.getNickNameById(flowApply.getCreateUserId());
            flowApply.setCreateUserName(nickName);
        }

        return flowApply;
    }

    public FlowApply getByNumber(String number) {

        LambdaQueryWrapper<FlowApply> qw = new LambdaQueryWrapper<>();
        qw.eq(FlowApply::getNumber, number);
        FlowApply flowApply = flowApplyMapper.selectOne(qw);
        if (flowApply!=null) {
            String nickName = commonUserService.getNickNameById(flowApply.getCreateUserId());
            flowApply.setCreateUserName(nickName);
        }
        return flowApply;
    }

    public FlowApplyDetailDTO getDetailById(String id) {
        FlowApply flowApply = getById(id);
        return flowApplyConvert.dao2detail(flowApply);
    }

    public FlowApplyDetailDTO getDetailByNumber(String number) {
        FlowApply flowApply = getByNumber(number);
        return flowApplyConvert.dao2detail(flowApply);
    }

    public void finish(String id) {
        FlowApply flowApply = flowApplyMapper.selectById(id);
        flowApply.setState(ApplyStateEnum.FINISH.getValue());
        flowApplyMapper.updateById(flowApply);
    }

    public void updateState(String id, ApplyStateEnum state) {
        FlowApply apply = getById(id);
        apply.setState(state.getValue());
        flowApplyMapper.updateById(apply);
    }

    public List<FlowTask> getTaskListById(String id) {
        FlowApply apply = getById(id);
        String flowId = apply.getFlowId();
        if (flowId==null) {
            return null;
        }
        return flowService.getTaskList(flowId);

    }



}
